home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 4
/
Amiga Tools 4.iso
/
grafix
/
raytracing
/
raylab
/
source
/
platform
/
amiga
/
amiga.c
next >
Wrap
C/C++ Source or Header
|
1996-02-17
|
13KB
|
507 lines
/*
name: amiga.c
Amiga display routines
----------------------
Currently supported displaymodes:
0 - No display (default)
1 - HAM6, lowres, non-interlaced
2 - Grayscale (16 colors), hires, interlaced
*/
#include <stdio.h>
#include <dos.h>
#include <intuition/intuition.h>
#include <exec/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include "defs.h"
#include "extern.h"
/* Prototypes for some subroutines */
void OpenAmigaScreen(struct NewScreen *ScreenPars,struct NewWindow *WindowPars, UWORD Palette[], ULONG NumCols);
void CloseAmigaScreen(void);
UBYTE ConvertColorToHam6(unsigned char RGBColor[], int x, int y);
UBYTE ConvertColorToGray(unsigned char RGBColor[], int x, int y);
UBYTE MG_Dither8(UBYTE Value, int x, int y);
void MG_Dither24(UBYTE RGBColor12[],unsigned char RGBColor24[], int x, int y);
int BreakHandler(void);
/* Some declarations */
#define SCREEN_TITLE_HEIGHT 11
#define DISPLAY_NONE 0 /* Different display modes */
#define DISPLAY_HAM6 1
#define DISPLAY_GRAY 2
#define HAM_MODE_PAL 0x00
#define HAM_MODE_RED 0x20
#define HAM_MODE_GRN 0x30
#define HAM_MODE_BLU 0x10
/* Some global variables */
int CurrentDisplayType;
UBYTE Last12BitColor[3] = {0,0,0};
struct Screen *RL_Screen = NULL;
struct Window *RL_Window = NULL;
struct RastPort *RL_RastPort = NULL;
struct ViewPort *RL_ViewPort = NULL;
struct IntuitionBase *IntBase = NULL;
struct GfxBase *GfxBase = NULL;
UWORD Ham6Palette[16] = {
0x000, 0xAAA, 0x555, 0xFFF,
0x808, 0xF4A, 0xE00, 0x620,
0xF60, 0xFA8, 0xFE0, 0x080,
0x0D0, 0x0CC, 0x06F, 0x00A
};
UWORD GrayPalette[16] = {
0x000, 0x111, 0x222, 0x333,
0x444, 0x555, 0x666, 0x777,
0x888, 0x999, 0xAAA, 0xBBB,
0xCCC, 0xDDD, 0xEEE, 0xFFF
};
UWORD DitherMask[16] = {
0x8000, 0x8080, 0x8410, 0x8888,
0x9224, 0xA492, 0xA94A, 0xAAAA,
0xD555, 0xD6B5, 0xDB6D, 0xEDDB,
0xF777, 0xFBEF, 0xFF7F, 0xFFFF
};
UBYTE DitherYTable[16] = {
0x08, 0x0B, 0x0E, 0x0F, 0x10, 0x0F, 0x0E, 0x0B,
0x08, 0x05, 0x02, 0x01, 0x00, 0x01, 0x02, 0x05
};
struct TextAttr TopazAttr =
{(STRPTR)"topaz.font",TOPAZ_EIGHTY,0,0};
/******************************************************************
*
* OpenDisplay()
*
******************************************************************/
long OpenDisplay(long DisplayType)
{
long Ret_OK;
struct NewScreen ScreenPars =
{
0, 0, /* LeftEdge, TopEdge */
NULL, NULL, /* Set screen size later */
NULL, /* Set depth later */
2, 7, /* DetailPen, BlockPen */
NULL, /* Set display-mode later */
CUSTOMSCREEN, /* SCREENQUIET ? */
NULL, /* Set font later */
"RayLab 1.0 display", /* Title */
NULL, /* No special gadgets */
NULL /* Nu custom bitmap */
};
struct NewWindow WindowPars =
{
0, SCREEN_TITLE_HEIGHT, /* LeftEdge, TopEdge*/
NULL, NULL, /* Set screen size later */
3, 7, /* DetailPen, BlockPen */
MENUPICK, /* IDCMP */
SMART_REFRESH | BORDERLESS | NOCAREREFRESH | ACTIVATE,
NULL, /* No special gadgets */
NULL, /* No checkmark */
NULL, /* No window title */
NULL, /* Set screen later */
NULL, /* No bitmap */
NULL, NULL, /* Set min size later */
NULL, NULL, /* Set max size later */
CUSTOMSCREEN
};
RL_Screen = NULL; RL_Window = NULL;
(void) onbreak((int (*)(void))BreakHandler); /* Install break-handler */
IntBase = (struct IntuitionBase *)
OpenLibrary("intuition.library",33);
if(IntBase==NULL) {
fprintf(stderr,"Error: Could not open intuition.library; no display possible\n\n");
IntBase = NULL;
}
else {
GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library",33);
if(GfxBase==NULL) {
fprintf(stderr,"Error: Could not open graphics.library; no display possible\n\n");
CloseLibrary((struct Library *)IntBase);
IntBase = NULL; GfxBase = NULL;
}
}
if( (IntBase!=NULL) && (GfxBase!=NULL) ) {
if( (DisplayType>DISPLAY_NONE) && (DisplayType<=DISPLAY_GRAY) ) {
CurrentDisplayType = DisplayType;
ScreenPars.Width = (SHORT)PicWidth;
ScreenPars.Height = (SHORT)(PicHeight+SCREEN_TITLE_HEIGHT);
ScreenPars.Font = &TopazAttr;
WindowPars.Width = (SHORT)PicWidth;
WindowPars.Height = (SHORT)PicHeight;
WindowPars.MinWidth = WindowPars.MaxWidth = (SHORT)PicWidth;
WindowPars.MinHeight = WindowPars.MaxHeight = (SHORT)PicHeight;
switch(CurrentDisplayType) {
case DISPLAY_HAM6:
ScreenPars.ViewModes = HAM;
ScreenPars.Depth = 6;
OpenAmigaScreen(&ScreenPars,&WindowPars,Ham6Palette,16L);
break;
case DISPLAY_GRAY:
ScreenPars.ViewModes = HIRES | LACE;
ScreenPars.Depth = 4;
OpenAmigaScreen(&ScreenPars,&WindowPars,GrayPalette,16L);
break;
case DISPLAY_NONE:
break;
}
}
else {
if(DisplayType!=DISPLAY_NONE)
fprintf(stderr,"Warning: Unsupported display type (%d), no display opened\n\n",DisplayType);
CurrentDisplayType = DISPLAY_NONE;
}
}
else {
CurrentDisplayType = DISPLAY_NONE;
}
Ret_OK = 0L;
if(CurrentDisplayType!=DISPLAY_NONE) {
Ret_OK = 1L;
}
return(Ret_OK);
}
/******************************************************************
*
* CloseDisplay()
*
******************************************************************/
void CloseDisplay(void)
{
ULONG done, signalmask, signals, class, code, menunum, itemnum;
struct IntuiMessage *message;
if((CurrentDisplayType!=0)&&(picturerendering!=0)) {
CloseAmigaScreen();
}
else if((CurrentDisplayType!=0)&&(picturerendering==0)) {
struct IntuiText ItemsText[] =
{
{2,1,JAM1,2,1,NULL," Close", NULL}
};
struct MenuItem Items[] =
{
{
NULL, /* No more items */
0, 1, 110, 10, /* Left, top, width, height */
ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHBOX,
0, /* MutualExclude */
NULL, /* Set item text later */
NULL,
'C', /* Key equivalent */
NULL, /* Sub item */
MENUNULL /* NextSelect */
}
};
struct Menu MenuPars =
{
NULL, /* No more menus */
0, 0, 120, 40, /* Left, top, width, height */
MENUENABLED, /* Flags */
"Action", /* Menu name */
NULL /* Set first item later */
};
ItemsText[0].ITextFont = &TopazAttr;
Items[0].ItemFill = &ItemsText[0];
MenuPars.FirstItem = &Items[0];
SetMenuStrip(RL_Window, &MenuPars); /* Add menu */
signalmask = 1L << RL_Window->UserPort->mp_SigBit;
done = 0L;
while( done == 0L ) {
signals = Wait(signalmask);
if((signals&signalmask)!=0L) {
while( message = (struct IntuiMessage *)GetMsg(RL_Window->UserPort) ) {
class = message->Class;
code = message->Code;
ReplyMsg((struct Message *)message);
if(class==MENUPICK) {
menunum = MENUNUM(code);
itemnum = ITEMNUM(code);
if(menunum==0L) {
if(itemnum==0L) {
CloseAmigaScreen();
done = 1L;
}
}
}
}
}
}
}
}
/******************************************************************
*
* DisplayPlot()
*
******************************************************************/
void DisplayPlot(int x, int y, unsigned char RGBColor[])
{
switch(CurrentDisplayType) {
case DISPLAY_NONE:
break;
case DISPLAY_HAM6:
SetAPen(RL_RastPort, ConvertColorToHam6(RGBColor,x,y));
(void) WritePixel(RL_RastPort,x,y);
break;
case DISPLAY_GRAY:
SetAPen(RL_RastPort, ConvertColorToGray(RGBColor,x,y));
(void) WritePixel(RL_RastPort,x,y);
break;
}
}
/******************************************************************
This routine is called if CTRL-C is issued
******************************************************************/
int BreakHandler(void)
{
fprintf(stderr,"\n*** The execution of RayLab was terminated by the user\n");
cleanup();
return(1); /* Exit RayLab after this */
}
/******************************************************************
Some routines for converting 24-bit rgb colors to apropriate
display-modes
******************************************************************/
UBYTE ConvertColorToHam6(unsigned char RGBColor[], int x, int y) {
UBYTE New12BitColor[3];
UBYTE HamMode, HamCol;
long Diff12BitColor[3];
register long RGBDiff, t1, t2, t3, t4, i, BestColor;
if(x==0) {
t1 = Ham6Palette[0];
Last12BitColor[0] = (t1&0xf00)>>8;
Last12BitColor[1] = (t1&0x0f0)>>4;
Last12BitColor[2] = t1&0x00f;
}
/* When dithering, it seems best to use the 24-bit color for comparsion: */
Diff12BitColor[0] = (long)RGBColor[0]-(long)(Last12BitColor[0]<<4);
Diff12BitColor[1] = (long)RGBColor[1]-(long)(Last12BitColor[1]<<4);
Diff12BitColor[2] = (long)RGBColor[2]-(long)(Last12BitColor[2]<<4);
Diff12BitColor[0] *= Diff12BitColor[0];
Diff12BitColor[1] *= Diff12BitColor[1];
Diff12BitColor[2] *= Diff12BitColor[2];
HamMode = HAM_MODE_RED;
if(Diff12BitColor[1]>Diff12BitColor[0]) {
HamMode = HAM_MODE_GRN;
if(Diff12BitColor[2]>Diff12BitColor[1]) {
HamMode = HAM_MODE_BLU;
}
}
else {
if(Diff12BitColor[2]>Diff12BitColor[0]) {
HamMode = HAM_MODE_BLU;
}
}
Diff12BitColor[0] = Diff12BitColor[0]>>8;
Diff12BitColor[1] = Diff12BitColor[1]>>8;
Diff12BitColor[2] = Diff12BitColor[2]>>8;
MG_Dither24(New12BitColor,RGBColor,x,y);
switch(HamMode) {
case HAM_MODE_RED:
HamCol = Last12BitColor[0] = New12BitColor[0];
RGBDiff = Diff12BitColor[1] + Diff12BitColor[2];
break;
case HAM_MODE_GRN:
HamCol = Last12BitColor[1] = New12BitColor[1];
RGBDiff = Diff12BitColor[0] + Diff12BitColor[2];
break;
case HAM_MODE_BLU:
HamCol = Last12BitColor[2] = New12BitColor[2];
RGBDiff = Diff12BitColor[0] + Diff12BitColor[1];
break;
}
BestColor = 100;
for(i=0;i<16;i++) {
t1 = (long)Ham6Palette[i];
t2 = ((t1&0xf00)>>8) - (long)New12BitColor[0]; t2 *= t2;
t3 = ((t1&0x0f0)>>4) - (long)New12BitColor[1]; t3 *= t3;
t4 = (t1&0x00f) - (long)New12BitColor[2]; t4 *= t4;
t1 = t2+t3+t4;
if(RGBDiff>t1) {
RGBDiff = t1;
BestColor = i;
}
}
if(BestColor<16) {
HamMode = HAM_MODE_PAL;
HamCol = (UBYTE)BestColor;
t1 = Ham6Palette[BestColor];
Last12BitColor[0] = (t1&0xf00)>>8;
Last12BitColor[1] = (t1&0x0f0)>>4;
Last12BitColor[2] = t1&0x00f;
}
return((UBYTE)(HamMode | (HamCol&0x0f)));
}
UBYTE ConvertColorToGray(unsigned char RGBColor[], int x, int y)
{
UBYTE Gray;
Gray = (UBYTE)(((UWORD)RGBColor[0]+(UWORD)RGBColor[1]+(UWORD)RGBColor[2])/(UWORD)3);
return(MG_Dither8(Gray,x,y));
}
/* This is some strange dithering method that */
/* I managed to produce late one night */
UBYTE MG_Dither8(UBYTE Value, int x, int y)
{
UBYTE Dithered;
Dithered = Value>>4;
if(Dithered<15) {
if(((0x01<<(((y<<2)+x+DitherYTable[y&0x000f])&0x000f))&DitherMask[Value&0x0f])!=0) Dithered++;
}
return(Dithered);
}
void MG_Dither24(UBYTE RGBColor12[], unsigned char RGBColor24[], int x, int y)
{
register int Dither;
RGBColor12[0] = (RGBColor24[0]>>4)&0x0f;
RGBColor12[1] = (RGBColor24[1]>>4)&0x0f;
RGBColor12[2] = (RGBColor24[2]>>4)&0x0f;
Dither = 0x01<<(((y<<2)+x+DitherYTable[y&0x000f])&0x000f);
if((RGBColor12[0]<15)&(Dither&DitherMask[RGBColor24[0]&0x0f])!=0) RGBColor12[0]++;
if((RGBColor12[1]<15)&(Dither&DitherMask[RGBColor24[1]&0x0f])!=0) RGBColor12[1]++;
if((RGBColor12[2]<15)&(Dither&DitherMask[RGBColor24[2]&0x0f])!=0) RGBColor12[2]++;
}
/*
A routine for simplifying the opening of Amiga screens and windows
*/
void OpenAmigaScreen(struct NewScreen *ScreenPars,struct NewWindow *WindowPars, UWORD Palette[], ULONG NumCols)
{
RL_Screen = (struct Screen *)OpenScreen(ScreenPars);
if(RL_Screen!=NULL) {
WindowPars->Screen = RL_Screen;
RL_Window = (struct Window *)OpenWindow(WindowPars);
if(RL_Window!=NULL) {
RL_RastPort = RL_Window->RPort;
RL_ViewPort = &(RL_Screen->ViewPort);
LoadRGB4(RL_ViewPort,Palette,NumCols);
SetDrMd(RL_RastPort, JAM1);
}
else {
RL_RastPort = NULL;
fprintf(stderr,"Error: Could not open display window\n\n");
CurrentDisplayType = DISPLAY_NONE;
CloseScreen(RL_Screen);
RL_Screen = NULL; RL_Window = NULL;
}
}
else {
fprintf(stderr,"Error: Could not open display screen\n\n");
CurrentDisplayType = DISPLAY_NONE;
RL_Screen = NULL; RL_Window = NULL;
}
}
void CloseAmigaScreen(void)
{
CurrentDisplayType = DISPLAY_NONE;
if(RL_Window!=NULL) {
if(RL_Window->MenuStrip)
ClearMenuStrip(RL_Window); /* Remove menu */
CloseWindow(RL_Window); /* Close window */
RL_Window = NULL;
}
if(RL_Screen!=NULL) {
CloseScreen(RL_Screen); /* Close screen */
RL_Screen = NULL;
}
if(GfxBase!=NULL) {
CloseLibrary((struct Library *)GfxBase); /* Close graphics.library */
GfxBase = NULL;
}
if(IntBase!=NULL) {
CloseLibrary((struct Library *)IntBase); /* Close intuition.library */
IntBase = NULL;
}
}